package 炫彩基类

import (
	common "gitee.com/go_888/xcgui/xcgui/common"
	xcc "gitee.com/go_888/xcgui/xcgui/xcc"
	"sync"
	"syscall"
	"unsafe"
)

var (
	uiThreadCallBackFunc func(data int) int                      // 真实执行的
	uiThreadCallBackPtr  = syscall.NewCallback(uiThreadCallBack) // 壳
	utLock               sync.Mutex
)

// uiThreadCallBack UI线程回调函数
func uiThreadCallBack(data int) int {
	return uiThreadCallBackFunc(data)
}

// XC_CallUiThreadEx 炫彩_调用界面线程, 调用UI线程, 设置回调函数, 在回调函数里操作UI.
//   - 与 XC_CallUiThread 的区别是: 本函数没有2000个回调上限的限制, 回调函数可以直接使用匿名函数.
//
// f: 回调函数.
//
// data: 传进回调函数的用户自定义数据.
func X炫彩_调用界面线程Ex(回调函数 func(参数 int) int, 参数 int) int {
	utLock.Lock()
	defer utLock.Unlock()
	uiThreadCallBackFunc = 回调函数
	r, _, _ := xC_CallUiThread.Call(uiThreadCallBackPtr, uintptr(参数))
	return int(r)
}

// XC_CallUT 炫彩_调用界面线程, 调用UI线程, 设置回调函数, 在回调函数里操作UI.
//   - 与 XC_CallUiThread 的区别是: 本函数没有2000个回调上限的限制, 回调函数可以直接使用匿名函数.
//   - 回调函数没有参数也没有返回值.
//
// f: 回调函数, 没有参数也没有返回值, 可以直接使用匿名函数.
func X炫彩_调用界面线程(回调函数 func()) {
	utLock.Lock()
	defer utLock.Unlock()
	uiThreadCallBackFunc = func(data int) int {
		回调函数()
		return 0
	}
	xC_CallUiThread.Call(uiThreadCallBackPtr, uintptr(0))
}

// CallUTAny 炫彩_调用界面线程, 调用UI线程, 设置回调函数, 在回调函数里操作UI.
//   - 与 XC_CallUiThread 的区别是: 本函数没有2000个回调上限的限制, 回调函数可以直接使用匿名函数.
//   - 可以传入任意参数.
//
// f: 回调函数.
//
// data: 传进回调函数的用户自定义数据.
func CallUTAny(f func(data ...interface{}) int, data ...interface{}) int {
	utLock.Lock()
	defer utLock.Unlock()

	uiThreadCallBackFunc = func(args int) int {
		s := common.UintPtrToSlice(uintptr(args))
		return f(s...)
	}

	var dataPtr uintptr
	if len(data) > 0 {
		dataPtr = uintptr(unsafe.Pointer(&data[0]))
	}
	r, _, _ := xC_CallUiThread.Call(uiThreadCallBackPtr, dataPtr)
	return int(r)
}

// Auto 用于在UI线程操作UI.
//   - 会自动判断当前是否在UI线程, 如果在UI线程则直接执行, 如果不在UI线程则会调用 XC_CallUT.
func Auto(f func()) {
	if IsUiThread() {
		f()
	} else {
		X炫彩_调用界面线程(f)
	}
}

// AutoInt 用于在UI线程操作UI.
//   - 会自动判断当前是否在UI线程, 如果在UI线程则直接执行, 如果不在UI线程则会调用 XC_CallUiThreadEx.
func AutoInt(f func(data int) int, data int) int {
	if IsUiThread() {
		return f(data)
	} else {
		return X炫彩_调用界面线程Ex(f, data)
	}
}

// AutoAny 用于在UI线程操作UI.
//   - 会自动判断当前是否在UI线程, 如果在UI线程则直接执行, 如果不在UI线程则会调用 CallUTAny.
func AutoAny(f func(data ...interface{}) int, data ...interface{}) int {
	if IsUiThread() {
		return f(data...)
	} else {
		return CallUTAny(f, data...)
	}
}

// UiThreader 用于在UI线程操作UI.
type UiThreader interface {
	UiThreadCallBack(data int) int // 回调函数, 把操作UI的代码写在这里面.
}

// XC_CallUiThreader 炫彩_调用界面线程, 调用UI线程, 设置回调函数, 在回调函数里操作UI. 与 XC_CallUiThread 的区别是: 本函数没有2000个回调上限的限制, 回调函数可以直接使用匿名函数.
//
// u: xc.UiThreader.
//
// data: 传进回调函数的用户自定义数据.
func X炫彩_调用界面线程1(u UiThreader, 参数 int) int {
	utLock.Lock()
	defer utLock.Unlock()
	uiThreadCallBackFunc = u.UiThreadCallBack
	r, _, _ := xC_CallUiThread.Call(uiThreadCallBackPtr, uintptr(参数))
	return int(r)
}

// SetBnClicks 给一个窗口或布局元素中所有的按钮注册按钮单击事件.
//
// 说明: 本函数是通过遍历子元素实现的, 只会给窗口和布局元素中的按钮注册事件, 像List, Tree, 滑块条等元素中的按钮不会注册, 想要更多可以自己实现一个.
//
//	HXCGUI 炫彩窗口句柄或布局元素句柄.
//
//	onBnClick 按钮单击事件回调函数.
func X设置所有按钮单击事件(窗口句柄 int, 回调函数 func(元素句柄 int, pbHandled *bool) int) {
	if X判断窗口(窗口句柄) {
		for i := int32(0); i < X窗口_取子对象数量(窗口句柄); i++ {
			hEle := X窗口_取子对象从索引(窗口句柄, i)
			switch X取对象类型(hEle) {
			case xcc.X对象句柄类型_布局元素:
				X设置所有按钮单击事件(hEle, 回调函数)
			case xcc.X对象句柄类型_按钮:
				X元素_注册事件C1(hEle, xcc.X元素事件_按钮_点击, 回调函数)
			}
		}
	} else if X取对象类型(窗口句柄) == xcc.X对象句柄类型_布局元素 {
		for i := int32(0); i < X元素_取子对象数量(窗口句柄); i++ {
			hEle := X元素_取子对象从索引(窗口句柄, i)
			switch X取对象类型(hEle) {
			case xcc.X对象句柄类型_布局元素:
				X设置所有按钮单击事件(hEle, 回调函数)
			case xcc.X对象句柄类型_按钮:
				X元素_注册事件C1(hEle, xcc.X元素事件_按钮_点击, 回调函数)
			}
		}
	}
}

// Font_Info_Name 将[32]uint16转换到string.
//
// arr: [32]uint16.
func Font_Info_Name(arr [32]uint16) string {
	return syscall.UTF16ToString(arr[0:])
}

func X矩形转换RECTF(矩形 X结构_矩形) X结构_矩形F {
	return X结构_矩形F{
		X左:   float32(矩形.X左),
		X右:  float32(矩形.X右),
		X上:    float32(矩形.X上),
		X下: float32(矩形.X下),
	}
}

// PointInRect 判断一个点是否在矩形范围内.
func X是否在矩形范围内(点 X结构_坐标, 矩形 X结构_矩形) bool {
	return 点.X坐标 <= 矩形.X右 && 点.X坐标 >= 矩形.X左 && 点.Y坐标 <= 矩形.X下 && 点.Y坐标 >= 矩形.X上
}
